package com.zjlp.im.netty.server;

import com.zjlp.im.netty.handler.DefaultExceptionHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.json.JsonObjectDecoder;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import com.zjlp.im.netty.handler.DefaultChannelHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 应该使用channel 而不用改用上下文
 */
public class EchoServer {

    private Logger log = LoggerFactory.getLogger(EchoServer.class);
    private final int SERVER_PORT = 9779;

    /**
     * 初始化TCP的server
     */
    public void initNettyServer() {
        // 启动服务
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        // 通过nio方式来接收连接和处理连接
        EventLoopGroup bossGroup = new NioEventLoopGroup(20,
                Executors.newFixedThreadPool(40));
        // 工作组
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        // 注册事件组
        serverBootstrap.group(bossGroup, workerGroup);
        // 设置nio类型的channel
        serverBootstrap.channel(NioServerSocketChannel.class);
        // 设置监听端口
        serverBootstrap.localAddress(new InetSocketAddress(SERVER_PORT));
        // 有连接到达时会创建一个channel
        serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                //解决粘包
                //pipeline.addLast("package",new LineBasedFrameDecoder(1024));
                //字符串加密
                //pipeline.addLast("encoder", new StringEncoder());

                //字符串解密
               /*pipeline.addLast("decoder", new StringDecoder());*/
                //JSON解密
                pipeline.addLast("decoderJSON",new JsonObjectDecoder());
                //消息处理
                pipeline.addLast("myhandler", new DefaultChannelHandler());
                pipeline.addLast("exception",new DefaultExceptionHandler());
            }
        }).childOption(ChannelOption.SO_KEEPALIVE, true).option(ChannelOption.CONNECT_TIMEOUT_MILLIS,3000).option(ChannelOption.SO_BACKLOG,1024);
        // 配置完成，开始绑定server，通过调用sync同步方法阻塞直到绑定成功
        try {
            ChannelFuture cf = serverBootstrap.bind().sync();
            System.out.println(EchoServer.class.getName()
                    + " started and listen on " + cf.channel().localAddress());
            cf.channel().closeFuture().sync();// 应用程序会一直等待，直到channel关闭
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        EchoServer echoServer = new EchoServer();
        System.out.println("服务端启动成功！！！");
        echoServer.initNettyServer();
    }
}
